﻿// See https://aka.ms/new-console-template for more information
using Microsoft.Extensions.DependencyInjection;
using Senparc.CO2NET.RegisterServices;
using Senparc.CO2NET;
using Microsoft.Extensions.Configuration;
using Senparc.CO2NET.Extensions;
using Senparc.CO2NET.Cache;
using System.Text;
using System.Net.Mail;

Console.WriteLine("Hello, Senparc!");


var configBuilder = new ConfigurationBuilder();
configBuilder.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

var config = configBuilder.Build();

//var senparcSetting = new SenparcSetting();
//config.GetSection("SenparcSetting").Bind(senparcSetting);

var senparcSetting = config.GetSection("SenparcSetting").Get<SenparcSetting>();

var services = new ServiceCollection();
services.AddMemoryCache();//添加内存缓存

//添加Senparc.CO2NET全局注册
services.AddSenparcGlobalServices(config);
Console.WriteLine("完成 CO2NET 全局注册");

//Start CO2NET
var register = RegisterService.Start(senparcSetting)
                              .UseSenparcGlobal();

register.ChangeDefaultCacheNamespace("SundaySharing-20221218");

var serviceProvider = services.BuildServiceProvider();

Senparc.CO2NET.Cache.CsRedis.Register.UseKeyValueRedisNow();

#region 委托和编译原理

//var list = new List<Action<DateTime>>();
//for (int j = 1; j <= 10; j++)
//{
//    string s = "abc";
//    Action<DateTime> act = (time)
//            => Console.WriteLine(j + "-" + time.ToString("mm:ss.ffff") + "/" + s);
//    list.Add(act);
//}

//foreach (var item in list)
//{
//    item.Invoke(SystemTime.Now.UtcDateTime);
//}

#endregion

//缓存锁（分布式缓存锁）
var redisCache = CacheStrategyFactory.GetObjectCacheStrategyInstance();
var totalCount = 0;
var lockDt = SystemTime.Now;
await redisCache.UpdateAsync("Count", 0);

List<Task<Task>> taskList = new List<Task<Task>>();

for (int i = 0; i < 2; i++)
{
    var index = i;

    var t = Task.Factory.StartNew(async () =>
    {
        totalCount++;

        using (var redisLock = await redisCache.BeginCacheLockAsync("SundaySharing", "Count"/*, 10, TimeSpan.FromSeconds(1)*/))
        {
            var threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine($"Task threadId {index}：{threadId}");
            Console.WriteLine($"等待开始：{index}-{SystemTime.Now}");

            await Task.Delay(2000);
            //Thread.Sleep(2000);

            Console.WriteLine($"等待结束：{index}-{SystemTime.Now}");

            var ss = await redisCache.GetAsync<DateTime>("Count1");

            var threadId2 = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine($"Task  threadId {index}：{threadId2}");

            var count0 = await redisCache.GetAsync<DateTime>("Count1");
            for (int j = 0; j < 100; j++)
            {
                var count1 = await redisCache.GetAsync<DateTime>("Count1");
                await redisCache.SetAsync("Count1", SystemTime.Now.ToString());
            }

            var count = await redisCache.GetAsync<int>("Count");


            //Senparc.CO2NET.Trace.SenparcTrace.SendApiLog($"HTML - {i}", html);

            //Console.WriteLine(html?.Substring(0,100));

            count++;
            redisCache.Update("Count", count);

        }

    });

    taskList.Add(t);
}

taskList.ForEach(t =>
{
    t.GetAwaiter();
});

Task.WaitAll(taskList
                .Select(t => t.Unwrap())
                .ToArray());

Console.WriteLine("=====Task执行完毕=====");

List<Task> taskListParallel = new List<Task>();
for (int i = 0; i < 2; i++)
{
    var index = i;

    var t = Task.Factory.StartNew(async () =>
    {
        totalCount++;

        using (var redisLock = await redisCache.BeginCacheLockAsync("SundaySharing", "Count"/*, 10, TimeSpan.FromSeconds(1)*/))
        {
            var threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine($"Parallel threadId {index}：{threadId}");
            Console.WriteLine($"等待开始：{index}-{SystemTime.Now}");

            //await Task.Delay(2000);
            //Thread.Sleep(2000);

            Console.WriteLine($"等待结束：{index}-{SystemTime.Now}");

            var ss = await redisCache.GetAsync<DateTime>("Count1");

            var threadId2 = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine($"Parallel threadId {index}：{threadId2}");

            var count0 = await redisCache.GetAsync<DateTime>("Count1");
            for (int j = 0; j < 100; j++)
            {
                var count1 = await redisCache.GetAsync<DateTime>("Count1");
                await redisCache.SetAsync("Count1", SystemTime.Now.ToString());
            }

            var count = await redisCache.GetAsync<int>("Count");


            //Senparc.CO2NET.Trace.SenparcTrace.SendApiLog($"HTML - {i}", html);

            //Console.WriteLine(html?.Substring(0,100));

            count++;
            redisCache.Update("Count", count);

        }

    });

    taskListParallel.Add(t);
}

taskListParallel.AsParallel().ForAll(t => t.GetAwaiter().GetResult());

Console.WriteLine("=====Parallel执行完毕=====");



var parallelResult = Parallel.For(0, 2, async i =>
{
    totalCount++;
    using (var redisLock = await redisCache.BeginCacheLockAsync("SundaySharing", "Count"/*, 10, TimeSpan.FromSeconds(1)*/))
    {
        var threadId = Thread.CurrentThread.ManagedThreadId;
        Console.WriteLine($"threadId {i}：{threadId}");
        Console.WriteLine($"等待开始：{i}-{SystemTime.Now}");

        await Task.Delay(2000);
        //Thread.Sleep(2000);

        Console.WriteLine($"等待结束：{i}-{SystemTime.Now}");

        var ss = await redisCache.GetAsync<DateTime>("Count1");

        var threadId2 = Thread.CurrentThread.ManagedThreadId;
        Console.WriteLine($"threadId {i}：{threadId2}");

        var count0 = await redisCache.GetAsync<DateTime>("Count1");
        for (int j = 0; j < 100; j++)
        {
            var count1 = await redisCache.GetAsync<DateTime>("Count1");
            await redisCache.SetAsync("Count1", SystemTime.Now.ToString());
        }

        var count = await redisCache.GetAsync<int>("Count");


        //Senparc.CO2NET.Trace.SenparcTrace.SendApiLog($"HTML - {i}", html);

        //Console.WriteLine(html?.Substring(0,100));

        count++;
        redisCache.Update("Count", count);

    }
});

Console.WriteLine(parallelResult.ToJson(true));
Console.WriteLine("等待时间：" + SystemTime.DiffTotalMS(lockDt));

var finalCount = await redisCache.GetAsync("Count");

Console.WriteLine($"count:{finalCount}/{totalCount}");

Console.ReadKey();